home *** CD-ROM | disk | FTP | other *** search
- Subject: v09i031: A TECO text editor, Part04/04
- Newsgroups: mod.sources
- Approved: rs@mirror.TMC.COM
-
- Submitted by: genrad!mlf
- Mod.sources: Volume 9, Issue 31
- Archive-name: teco/Part04
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If this archive is complete, you will see the message:
- # "End of archive 4 (of 4)."
- # Contents: te_window.c
- # Wrapped by rs@mirror on Thu Mar 12 19:54:35 1987
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo shar: Extracting \"te_window.c\" \(33018 characters\)
- if test -f te_window.c ; then
- echo shar: Will not over-write existing file \"te_window.c\"
- else
- sed "s/^X//" >te_window.c <<'END_OF_te_window.c'
- X/* TECO for Ultrix Copyright 1986 Matt Fichtenbaum */
- X/* This program and its components belong to GenRad Inc, Concord MA 01742 */
- X/* They may be copied if this copyright notice is included */
- X
- X/* te_window.c window for teco 10/10/86 */
- X/* This attempts to be a real window, without unecessary redraw */
- X/* it is very VT-100 specific, and ought to be rewritten to be general */
- X
- X#include "te_defs.h"
- X
- X/* maximum screen height and width (horiz and vert, not height and vidth) */
- X#define W_MAX_V 70
- X#define W_MAX_H 150
- X#define MAX 0x7fffffff /* maximum positive integer, for "last modified" location */
- X#define W_MARK 0200 /* "this loc is special" in screen image */
- X
- X
- X/* image of current window */
- X
- Xstruct w_line /* data associated with one screen line */
- X {
- X int start, end; /* dot at beginning, at end */
- X short n, cflag, col; /* number of char positions used, line continuation flag, starting col */
- X char ch[W_MAX_H]; /* image of line */
- X }
- X w_image[W_MAX_V];
- X
- X
- X/* define "this line is continued" / "this line is a continuation" flags */
- X#define WF_BEG 1
- X#define WF_CONT 2
- X
- Xstruct w_line *wlp[W_MAX_V]; /* each word points to the corresponding line's data structure */
- X
- Xstruct qp w_p1; /* pointer for window access to buffer */
- X
- Xshort curr_x, curr_y; /* active character position */
- Xshort term_x, term_y; /* current terminal cursor position */
- Xshort curs_x, curs_y; /* current teco dot screen coordinates */
- Xshort last_y; /* last used line in window */
- Xchar curs_c; /* code for char at cursor */
- Xchar *curs_p; /* pointer to cursor loc in window image */
- Xshort curs_crflag; /* flag that cursor is on a CR */
- Xshort redraw_sw; /* forces absolute redraw */
- X
- X
- X/* fill characters and terminal speeds: 0th entry used when std out is not a terminal */
- Xchar win_speeds[] = { 0, 0, B9600, B4800, B2400, B1800, B1200, B600, B300, B200, B150, B134, B110 };
- Xchar win_dlye[] = { 0, 90, 45, 23, 11, 9, 6, 3, 1, 1, 1, 1, 1 }; /* delay for erase-screen */
- Xchar win_dlys[] = { 0, 60, 30, 15, 7, 6, 4, 2, 1, 1, 0, 0, 0 }; /* delay for scroll ops */
- Xchar win_dlyl[] = { 0, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* delay for erase line */
- Xchar win_dlyc[] = { 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* delay for other control functions */
- Xshort win_speed;
- X/* routine to perform simple scope operations */
- X/* (an attempt to concentrate VT-100 specific things in one place) */
- X
- Xvt(func)
- X int func;
- X {
- X short t;
- X switch (func)
- X {
- X case VT_CLEAR: /* clear screen */
- X fputs("\033[H\033[J", stdout);
- X for (t = 0; t < win_dlye[win_speed]; t++) putchar('\0'); /* fill chars */
- X break;
- X
- X case VT_EEOL: /* erase to end of line */
- X fputs("\033[K", stdout);
- X for (t = 0; t < win_dlyl[win_speed]; t++) putchar('\0'); /* fill chars */
- X break;
- X
- X case VT_EBOL: /* erase from beginning of line */
- X fputs("\033[1K", stdout);
- X for (t = 0; t < win_dlyl[win_speed]; t++) putchar('\0'); /* fill chars */
- X break;
- X
- X case VT_SETSPEC1: /* reverse video */
- X fputs("\033[7m", stdout);
- X break;
- X
- X case VT_SETSPEC2: /* bright reverse video */
- X fputs("\033[1;7m", stdout);
- X break;
- X
- X case VT_CLRSPEC: /* normal video */
- X fputs("\033[0m", stdout);
- X break;
- X
- X case VT_BS1: /* backspace 1 spot */
- X fputs("\b \b", stdout);
- X break;
- X
- X case VT_BS2: /* backspace 2 spots */
- X fputs("\b \b\b \b", stdout);
- X break;
- X
- X case VT_LINEUP: /* up one line */
- X fputs("\033[1A", stdout);
- X break;
- X }
- X }
- X/* routine to set window parameters */
- X
- X/* 0: scope type, 1: width, 2: height, 3: seeall, 4: mark position, */
- X/* 5: hold mode, 6: upper left corner position, 7: scroll region size */
- X
- X/* 0 1 2 3 4 5 6 7 */
- Xint win_min[] = { 4, 20, 4, 0, 0, -1, 1, 0 } ; /* min values for window parameters */
- Xint win_max[] = { 4, W_MAX_H, W_MAX_V, 1, MAX, 12, -1, 20 } ; /* max values */
- Xint win_data[] = { 4, 132, 24, 0, 0, 0, 0, 0 } ; /* window parameters */
- X
- Xint window_size; /* # of lines in a window */
- X
- Xdo_window(ref_flag)
- X int ref_flag; /* nonzero forces "refresh" operation */
- X {
- X int i;
- X
- X if (colonflag && !ref_flag)
- X {
- X i = get_value(0); /* get sub-function */
- X if ((i < 0) || (i > 7)) ERROR(E_IWA);
- X if (!esp->flag2) /* it's a "get" */
- X {
- X esp->val1 = win_data[i];
- X esp->flag1 = 1;
- X }
- X else
- X {
- X if ((esp->val2 < win_min[i]) || (esp->val2 > win_max[i])) /* check range */
- X ERROR(E_IWA);
- X if (i == 7)
- X {
- X if (esp->val2)
- X {
- X WN_scroll = esp->val2;
- X window_size = WN_height - WN_scroll; /* define size of window area */
- X window(WIN_INIT); /* turn on window */
- X }
- X else window(WIN_OFF); /* turn off window */
- X }
- X win_data[i] = esp->val2; /* redundant for ~0,7:w, but no harm */
- X esp->flag2 = 0;
- X window(WIN_REDRAW); /* redraw window */
- X }
- X }
- X
- X else /* no colon, or ^W command */
- X {
- X if (esp->flag1 || ref_flag)
- X {
- X if (!ref_flag && (esp->val1 == -1000)) redraw_sw = 0; /* -1000W: "forget that output was done" */
- X else window(WIN_DISP); /* nW or ^W refreshes window */
- X }
- X esp->flag2 = esp->flag1 = 0; /* no colon, consume args */
- X }
- X colonflag = 0;
- X esp->op = OP_START;
- X }
- X/* routine to update screen size with numbers obtained from environment */
- X/* (called by main program's initialization) */
- X
- Xset_term_par(lines, cols)
- X int lines, cols;
- X {
- X if ((lines >= win_min[2]) && (lines <= win_max[2])) window_size = win_data[2] = lines;
- X if ((cols >= win_min[1]) && (cols <= win_max[1])) win_data[1] = cols;
- X }
- X
- X
- X/* window routine. performs function as indicated by argument */
- X/* WIN_OFF: disables split-screen scrolling */
- X/* WIN_SUSP: disables split-screen scrolling temporarily */
- X/* WIN_INIT: sets up display support if split-screen scrolling enabled, else nop */
- X/* WIN_RESUME: re-enables display support */
- X/* WIN_REDRAW: causes window to be redrawn on next refresh call */
- X/* WIN_REFR: if scrolling enabled, redoes window, else if ev or es enabled, does */
- X/* that, else nop */
- X/* WIN_LINE: does WIN_REFR unless that wouldn't do anything, in which case */
- X/* it does effective 1EV output */
- X
- Xint last_dot = -1; /* last dot location */
- X
- Xwindow(arg)
- X int arg;
- X {
- X int i;
- X
- X switch (arg)
- X {
- X case WIN_OFF: /* final window off */
- X case WIN_SUSP: /* temp window off */
- X if (WN_scroll) /* if reset/clean up */
- X {
- X /* full margins, cursor to last line, erase line */
- X printf("\033[r\033[%d;0H\033[K", WN_height);
- X }
- X break;
- X
- X case WIN_INIT: /* initialize window - find output speed */
- X if (out_noterm) win_speed = 0; /* std out is not a terminal */
- X else
- X {
- X for (win_speed = 1; (win_speeds[win_speed] != ttybuf.sg_ospeed) && (win_speed < 13); win_speed++);
- X if (win_speed == 13) win_speed = 1;
- X }
- X w_init(); /* set up screen image buffer */
- X if (WN_scroll) vt(VT_CLEAR); /* if split-screen is enabled, clear screen */
- X /* (fall through to "resume") */
- X
- X case WIN_RESUME: /* re-enable window */
- X if (WN_scroll) /* set scroll region, cursor to bottom */
- X printf("\033[%d;%dr\033[%d;0H", WN_height - WN_scroll + 1, WN_height, WN_height);
- X break;
- X case WIN_REDRAW: /* force redraw of window */
- X redraw_sw = 1;
- X break;
- X
- X case WIN_LINE: /* display one line unless window enabled or ev */
- X if (WN_scroll || ev_val) window(WIN_REFR); /* if a real window is set, do it */
- X else if (w_setptr(dot, &w_p1)) /* set pointer to dot... and if there's a buffer */
- X {
- X w_lines(0, &w_p1, &w_p1); /* get to beginning of line */
- X window0(1); /* and type 1 line */
- X }
- X break;
- X
- X case WIN_REFR: /* if enabled, refresh window; else do ev or es */
- X if (WN_scroll) window1(); /* if scrolling enabled, refresh the window */
- X else if ((ev_val) || (es_val && search_flag)) /* else if ev or es, do that */
- X {
- X i = (ev_val) ? ev_val : es_val;
- X if (w_setptr(dot, &w_p1)) /* set a pointer at dot... and if there's a buffer */
- X window0(i - w_lines(1 - i, &w_p1, &w_p1)); /* go back (i-1) lines and ahead (i) lines */
- X }
- X break;
- X
- X case WIN_DISP: /* display buffer independent of whether scroll mode is enabled */
- X window1();
- X break;
- X
- X } /* end of switch */
- X
- X fflush(stdout); /* send output out */
- X } /* end of window() */
- X/* routine to type n lines with character at "dot" in reverse video */
- X/* used for ev, es, and <BS> or <LF> as immediate commands */
- X/* starting char position is in w_p1; argument is number of lines */
- X
- Xwindow0(num)
- X int num;
- X {
- X int wi;
- X char wc; /* temp char */
- X
- X for (wi = w_p1.dot; (num > 0) && (wi < z); wi++) /* for each character */
- X {
- X wc = w_p1.p->ch[w_p1.c]; /* get character */
- X
- X if ((char_count >= WN_width) && (wc != CR) && !(spec_chars[wc] & A_L)) /* if about to exceed width */
- X {
- X if (et_val & ET_TRUNC) goto w0_noprint; /* truncate: don't print this */
- X else
- X {
- X fputs("\033[K\015\012\033(0h\033(B ", stdout); /* <eeol> "NL space" */
- X char_count = 2;
- X --num; /* one fewer line remaining */
- X }
- X }
- X
- X if (wi == dot) /* if this char is at the pointer */
- X {
- X vt(VT_SETSPEC2); /* set reverse video */
- X if (wc == TAB)
- X {
- X type_char(' '); /* illuminate the first sp of a tab */
- X vt(VT_CLRSPEC); /* clear reverse video */
- X if (char_count & tabmask) type_char(TAB);
- X }
- X else /* not a tab */
- X {
- X if ((wc == CR) && (char_count < WN_width)) /* CR at rh margin: don't display cursor */
- X {
- X type_char(' '); /* cr: put a space after line */
- X vt(VT_EEOL); /* erase to eol */
- X }
- X type_char(wc); /* type the char, or exec CR */
- X if (wc == LF)
- X {
- X fputs("\033(0", stdout);
- X type_char('e');
- X fputs("\033(B", stdout);
- X }
- X vt(VT_CLRSPEC); /* clear reverse video */
- X }
- X }
- X else /* this is not char at pointer */
- X {
- X if (wc == CR && curr_x < WN_width) vt(VT_EEOL); /* erase to EOL */
- X type_char(wc);
- X }
- X if ((wc == FF) || (wc == VT)) /* FF & VT end a line */
- X {
- X vt(VT_EEOL); /* erase rest of this line */
- X crlf(); /* and leave a blank one */
- X if (!(ez_val & EZ_NOVTFF)) --num; /* if FF and VT count as line sep's, count them */
- X }
- X
- X w0_noprint:
- X if (++w_p1.c > CELLSIZE-1) w_p1.p = w_p1.p->f, w_p1.c = 0; /* next char */
- X if (wc == LF) --num; /* if this is a line feed, count lines */
- X }
- X
- X if (dot == z) fputs("\033[1;7m \033[0m\033[0K", stdout); /* type one space and erase rest of line */
- X else fputs("\033[0K", stdout); /* else just erase to EOL */
- X }
- X/* routine to maintain the screen window */
- X/* if scroll mode is enabled, the VT100 screen is split and only the upper part */
- X/* is used by this routine; else the whole screen is used. */
- X
- Xwindow1()
- X {
- X int i, j, m, lflag;
- X
- X if (!redraw_sw && (dot == last_dot) && (buff_mod == MAX)) return; /* return if nothing has changed */
- X
- X block_inter(1); /* disable ^C interrupts */
- X if (WN_scroll) printf("\033[1;%dr", window_size); /* scroll mode: redefine scroll region */
- X printf("\033[H"); /* home */
- X term_y = term_x = 0; /* indicate cursor is at home */
- X
- X if ((redraw_sw) || (z <= wlp[0]->start)) window1_abs(); /* forced redraw, or z before start of screen */
- X
- X
- X/* check whether pointer is before modified buffer location */
- X
- X else if (buff_mod >= dot) /* yes */
- X {
- X
- X if (dot < wlp[0]->start) /* if dot is before screen */
- X {
- X w_setptr(wlp[0]->start, &w_p1); /* get to beginning of screen */
- X
- X /* check whether screen begins with the last part of a continued line */
- X for (j = 0; (wlp[j]->cflag & WF_CONT) && (j < window_size/2); j++);
- X if (j < window_size/2) /* if so, does it continue less than halfway down the screen? */
- X {
- X
- X if (j) /* is there a partial line? */
- X {
- X w_lines(0, &w_p1, &w_p1); /* 0L */
- X j -= w_lines(1, &w_p1, NULL); /* now j is number of display lines before screen */
- X }
- X /* now look for how many lines back "dot" is: if screen starts with partial line, w_p1 has already been moved */
- X /* to beginning of the line and j equals the count of extra lines to scroll */
- X
- X for (i = 0; (dot < w_p1.dot) && (i < window_size/2); ) i -= w_lines(-1, &w_p1, &w_p1);
- X if ((dot >= w_p1.dot) && (i < window_size)) /* found point within reason */
- X {
- X w_scroll(j - i); /* scroll screen down that many lines */
- X curr_y = wlp[0]->cflag = wlp[0]->col = curr_x = 0; /* start from top of screen */
- X wlp[0]->start = w_p1.dot; /* save starting char position */
- X window2(0); /* and rewrite screen */
- X }
- X
- X else window1_abs(); /* farther back than that - redraw */
- X }
- X
- X else window1_abs(); /* continuation was too long: give up and redraw */
- X } /* end of "dot is before screen" */
- X
- X else if (dot <= wlp[last_y]->end) window1_inc(dot); /* on screen - redraw incrementally */
- X
- X else window1_after(); /* dot is after screen: scroll or redraw */
- X } /* end of "dot is before modified point" */
- X
- X
- X/* the modified point in the buffer is before dot */
- X
- X else
- X {
- X if (buff_mod < wlp[0]->start) window1_abs(); /* modified point before screen - redraw fully */
- X
- X else if (buff_mod <= wlp[last_y]->end) /* modified point on screen */
- X {
- X for (m = 0; buff_mod > wlp[m]->end; m++); /* find line with buff_mod */
- X w_setptr(wlp[m]->start, &w_p1); /* set a pointer to start of line with buff_mod */
- X j = (m < window_size/2) ? window_size - 1 - m : window_size/2; /* maximum # of lines between buff_mod & dot */
- X for (i = 0; (dot >= w_p1.dot) && (w_p1.dot < z) && (i <= j); )
- X i += (lflag = w_lines(1, &w_p1, &w_p1) ) ? lflag : 1; /* count lines from buff_mod to first line after dot */
- X if (i > j) window1_abs(); /* too far - redraw */
- X else
- X {
- X if (lflag && (dot == z)) i++; /* if at end, following a LF */
- X w_setptr(wlp[m]->start, &w_p1); /* pointer to start of area to redraw */
- X if (i >= window_size - m) /* if there are not enough blank lines on screen */
- X w_scroll(i = i - window_size + m), curr_y = m - i, curs_y -= i; /* scroll up the difference */
- X else curr_y = m;
- X curr_x = (wlp[curr_y]->cflag & WF_CONT) ? 2 : wlp[curr_y]->col; /* line starts at left unless continuation */
- X if ((curr_y > curs_y) && (curs_y >= 0)) w_rmcurs(); /* remove old cursor if it won't be written over */
- X window2(0); /* rewrite newly cleared region */
- X for (curr_x = 0; ++curr_y < window_size; ) /* clear rest of screen if needed */
- X {
- X wlp[curr_y]->cflag = 0;
- X if (wlp[curr_y]->n) wlp[curr_y]->n = 0, vtm(VT_EEOL);
- X }
- X }
- X } /* end "modified point on screen */
- X
- X else window1_after(); /* modified point after screen: scroll or redraw as appropriate */
- X }
- X/* done redrawing: do cleanup work */
- X
- X if (WN_scroll)
- X {
- X printf("\033[%d;%dr", window_size+1, WN_height); /* reset margins */
- X printf("\033[%d;0H", WN_height); /* cursor to bottom */
- X }
- X else printf("\033[H"); /* no split screen: set home */
- X
- X fflush(stdout); /* flush output */
- X WN_origin = wlp[0]->start; /* save first char pos on screen */
- X redraw_sw = 0; /* mark screen as updated */
- X buff_mod = MAX;
- X last_dot = dot;
- X block_inter(0); /* reenable interrupts */
- X }
- X/* routine to redraw screen absolutely */
- X
- Xwindow1_abs()
- X {
- X int i, j;
- X
- X curr_y = wlp[0]->col = curr_x = 0; /* indicate where refresh starts */
- X set_pointer(dot, &w_p1); /* make a text buffer, if none, and refresh the display */
- X w_lines(0, &w_p1, &w_p1); /* do 0L */
- X if ((i = w_lines(window_size/2, &w_p1, NULL)) == 0) i = 1; /* check how many lines after dot */
- X if (i > window_size/2) i = window_size/2; /* limit amount after dot */
- X for (j = 0; (j < window_size - i) && (w_p1.dot > 0); ) /* find start of display area */
- X j -= w_lines(-1, &w_p1, &w_p1);
- X if (j > window_size - i) w_lines(1, &w_p1, &w_p1); /* if too far back, move up one line */
- X
- X wlp[0]->start = w_p1.dot; /* indicate where first window line starts */
- X window2(0); /* refresh the whole display */
- X
- X for (curr_x = 0; ++curr_y < window_size; ) /* blank out lines not written by window2 */
- X if (wlp[curr_y]->n || redraw_sw) wlp[curr_y]->n = 0, vtm(VT_EEOL);
- X }
- X
- X
- X
- X
- X/* redraw screen incrementally */
- X
- Xwindow1_inc(wd)
- X int wd; /* argument is earliest change */
- X {
- X short temp_y;
- X
- X/* find the line containing the character at wd */
- X
- X for (temp_y = 0; wd > wlp[temp_y]->end; temp_y++);
- X
- X if ((curs_y != temp_y) || (buff_mod == MAX) || curs_crflag) /* if the cursor line won't be rewritten */
- X w_rmcurs(); /* remove the old cursor */
- X curr_y = temp_y; /* and go to work on the beginning of the line with dot */
- X curr_x = (wlp[curr_y]->cflag & WF_CONT) ? 2 : wlp[curr_y]->col; /* line starts at left unless continuation */
- X
- X w_setptr(wlp[curr_y]->start, &w_p1); /* make a pointer there */
- X window2(buff_mod == MAX); /* if buffer not modified, redraw only the line with dot */
- X
- X if (buff_mod < MAX) /* if buffer has changed, erase display lines beyond end of buffer */
- X for (curr_x = 0; ++curr_y < window_size; )
- X if ( ((wlp[curr_y]->start >= z) || (wlp[curr_y]->start <= wlp[curr_y-1]->end)) && (wlp[curr_y]->n || redraw_sw) )
- X wlp[curr_y]->n = 0, vtm(VT_EEOL), wlp[curr_y]->cflag = 0;
- X }
- X/* routine to move window downwards: scroll up or redraw as appropriate */
- X
- Xwindow1_after()
- X {
- X int i, lflag;
- X
- X w_rmcurs(); /* remove old cursor */
- X w_setptr(wlp[window_size-1]->start, &w_p1); /* set pointer to start of last line on screen */
- X
- X for (i = 0; (dot >= w_p1.dot) && (w_p1.dot < z) && (i <= window_size/2); )
- X i += (lflag = w_lines(1, &w_p1, &w_p1)) ? lflag : 1; /* fwd one line at a time until > dot or end of buffer */
- X
- X if (i <= window_size/2) /* found within n lines */
- X {
- X if (lflag && (dot == z)) ++i; /* if dot is at end of buffer after a LF */
- X if (i >= window_size - last_y) /* if there are not enough blank lines on screen */
- X w_scroll(i - window_size + last_y), curr_y = window_size - i; /* scroll up the difference */
- X else curr_y = last_y;
- X
- X while (curr_y && (wlp[curr_y]->cflag & WF_CONT)) --curr_y; /* get to start of cont'd lines */
- X w_setptr(wlp[curr_y]->start, &w_p1); /* pointer to start of area to redraw */
- X curr_x = wlp[curr_y]->col; /* redraw starts at line's first column */
- X window2(0); /* rewrite newly cleared region */
- X }
- X
- X else window1_abs(); /* move down is too far: redraw fully */
- X }
- X
- X
- X
- X/* routine to remove the existing cursor */
- X
- Xw_rmcurs()
- X {
- X if (curs_c) /* if there was a cursor */
- X {
- X w_move(curs_y, curs_x); /* go remove the old cursor */
- X if (curs_c & W_MARK) fputs("\033(0", stdout); /* if prev char was a spec char */
- X putchar(*curs_p = curs_c); /* put back the char that was there */
- X if (curs_c & W_MARK) fputs("\033(B", stdout);
- X ++term_x; /* and keep the terminal cursor loc. happy */
- X }
- X }
- X/* routine to do actual display refresh */
- X/* called with w_p1 at starting char, curr_y, curr_x at starting coordinate */
- X/* rewrites to end of screen if arg = 0, or only until line with cursor if arg = 1 */
- X
- Xwindow2(arg)
- X int arg;
- X {
- X register int wdot;
- X register char wc; /* temp char */
- X register short dflag; /* nonzero if this is char at dot */
- X short cr_found; /* indicates a cr found on this line */
- X
- X cr_found = 0; /* clear "cr" flag in first line written */
- X for (wdot = w_p1.dot; (curr_y < window_size) && (wdot < z); wdot++) /* for each character */
- X {
- X wc = w_p1.p->ch[w_p1.c] & 0177; /* get character */
- X if (dflag = (wdot == dot)) if (arg) arg = -1; /* save "this is char at dot", "on line with dot" */
- X
- X if (wc < ' ') switch (wc) /* dispatch control characters */
- X {
- X case CR:
- X if (dflag) /* if cursor on this CR */
- X {
- X if (curr_x < WN_width) w_makecurs(' ', 1), w_type(' ', 1); /* display a space, unless at end */
- X else curs_crflag = curs_c = 0; /* else set "no cursor displayed" */
- X }
- X /* trim remainder of line if this is first cr and old line was longer */
- X if (!cr_found && ((curr_x < wlp[curr_y]->n) || redraw_sw))
- X {
- X wlp[curr_y]->n = curr_x;
- X if (curr_x < WN_width) vtm(VT_EEOL);
- X }
- X cr_found = 1; /* set cr flag */
- X wlp[curr_y]->cflag &= ~WF_BEG; /* this line is not continued */
- X while (curr_y && (wlp[curr_y]->cflag & WF_CONT)) --curr_y; /* if line is a continuation, scan up */
- X curr_x = 0;
- X break;
- X
- X case TAB:
- X if (curr_x >= WN_width)
- X {
- X if (et_val & ET_TRUNC) goto noprint;
- X if (w_overflow(wdot)) goto w2_exit; /* extend line */
- X }
- X if (dflag) w_makecurs(' ', 0);
- X w_type(' ', dflag); /* type one space */
- X if (dflag)
- X {
- X vt(VT_CLRSPEC); /* end reverse video */
- X dflag = 0;
- X }
- X while ((curr_x & tabmask) && (curr_x < WN_width)) w_type(' ', 0); /* finish tab */
- X break;
- X case LF:
- X while ((curr_y < window_size) && (wlp[curr_y]->cflag & WF_BEG)) ++curr_y; /* last screen row of this line */
- X wlp[curr_y]->end = wdot; /* save char position that ended this line */
- X if (dflag) /* if this LF is at dot */
- X { /* put cursor there, save char that was there */
- X w_makecurs( (curr_x < wlp[curr_y]->n) ? wlp[curr_y]->ch[curr_x] : ' ', 0);
- X fputs("\033(0", stdout); /* put in a "LF" char */
- X w_type('e', 1);
- X fputs("\033(B", stdout);
- X } /* if no cr found and not in last column, erase rest of line */
- X if (!cr_found && (curr_x < wlp[curr_y]->n))
- X {
- X wlp[curr_y]->n = curr_x;
- X if (curr_x < WN_width) vtm(VT_EEOL);
- X }
- X if (dflag) --curr_x; /* put the cursor back before the artificial LF char, if any */
- X if (curr_y >= window_size-1) /* if at end of screen, exit, but... */
- X {
- X if (dflag) vt(VT_CLRSPEC); /* if cursor is here, clear reverse video first */
- X goto w2_exit;
- X }
- X
- X if ((wlp[curr_y]->cflag & WF_CONT) && (wlp[curr_y]->end - wlp[curr_y]->start == 1)) /* if a now-empty cont. line, */
- X { /* flush it */
- X if (curr_y > 0) wlp[curr_y-1]->cflag &= ~WF_BEG; /* remove "cont'd" flag from prev line */
- X arg = 0; /* and force redraw of rest of screen */
- X if (curs_y == curr_y) curs_c = 0; /* if cursor was on this line, it will disappear */
- X }
- X else ++curr_y; /* down one line if not absorbing blank contin. line */
- X
- X wlp[curr_y]->start = wdot + 1; /* assume line starts with next char */
- X wlp[curr_y]->col = curr_x; /* save starting column */
- X cr_found = wlp[curr_y]->cflag = 0; /* clear line continuation flags */
- X if (curr_x) w_ebol(); /* if not at left margin, erase beginning of line */
- X if (arg == -1) /* finished line with dot... quit if spec'd */
- X {
- X if (dflag) /* but first, if at cursor, clear reverse video */
- X {
- X vt(VT_CLRSPEC);
- X dflag = 0;
- X }
- X return;
- X }
- X break;
- X
- X case ESC:
- X if (curr_x >= WN_width)
- X {
- X if (et_val & ET_TRUNC) goto noprint;
- X if (w_overflow(wdot)) goto w2_exit; /* extend line */
- X }
- X if (dflag) w_makecurs('$', 0);
- X w_type('$', dflag);
- X break;
- X default: /* all other control chars print as ^X */
- X if (curr_x >= WN_width - 1)
- X {
- X if (et_val & ET_TRUNC) goto noprint;
- X if (w_overflow(wdot)) goto w2_exit;
- X }
- X if (dflag) w_makecurs('^', 0);
- X w_type('^', dflag); /* ^ */
- X if (dflag)
- X {
- X vt(VT_CLRSPEC); /* if at cursor, clear reverse video */
- X dflag = 0;
- X }
- X w_type(wc | 0100, 0);
- X break;
- X } /* end "switch" */
- X else /* a printing character */
- X {
- X if (curr_x >= WN_width)
- X {
- X if (et_val & ET_TRUNC) goto noprint;
- X if (w_overflow(wdot)) goto w2_exit; /* extend line */
- X }
- X if (dflag) w_makecurs(wc, 0);
- X w_type(wc, dflag);
- X }
- X
- X if (dflag)
- X {
- X vt(VT_CLRSPEC); /* if at cursor, clear reverse video */
- X }
- X
- X if ((wc == FF) || (wc == VT)) /* these chars leave a display line blank */
- X {
- X if (redraw_sw || (curr_x < wlp[curr_y]->n))
- X {
- X wlp[curr_y]->n = curr_x;
- X if (curr_x < WN_width) vtm(VT_EEOL); /* erase rest of line */
- X }
- X wlp[curr_y]->end = wdot;
- X if (curr_y >= window_size-1) goto w2_exit; /* quit if overflow screen */
- X wlp[++curr_y]->start = wdot + 1;
- X cr_found = wlp[curr_y]->cflag = 0; /* init new line */
- X if (curr_x -= 2) w_ebol(); /* back up over ^X; if not at left margin, erase beginning of line */
- X wlp[curr_y]->col = curr_x; /* save starting column */
- X }
- X noprint:
- X if (++ w_p1.c > CELLSIZE - 1) w_p1.p = w_p1.p->f, w_p1.c = 0; /* next char in buffer */
- X } /* end of "for all characters" */
- X
- X if (dot == z)
- X {
- X if (curr_x < WN_width) w_makecurs(' ', 1), w_type(' ', 1), vt(VT_CLRSPEC); /* display a space, unless at end */
- X else curs_crflag = curs_c = 0; /* else set "no cursor displayed" */
- X }
- X
- X /* clear rest of line if needed */
- X if (!cr_found && (redraw_sw || (curr_x < wlp[curr_y]->n)))
- X {
- X wlp[curr_y]->n = curr_x;
- X if (curr_x < WN_width) vtm(VT_EEOL);
- X }
- X wlp[curr_y]->end = wdot; /* save char at end of last line */
- X w2_exit:
- X last_y = curr_y; /* record last used line on screen */
- X }
- X/* routine to move cursor to current location and then call vt */
- X
- Xvtm(arg)
- X int arg;
- X {
- X w_move(curr_y, curr_x);
- X vt(arg);
- X }
- X
- X
- X
- X
- X/* routine to set reverse video and save cursor location */
- X/* first argument is char at cursor, 2nd is value for curs_crflag */
- X
- Xw_makecurs(wc, crflag)
- X char wc;
- X short crflag;
- X {
- X curs_y = curr_y, curs_x = curr_x, curs_c = wc; /* save cursor coord and char */
- X curs_p = &wlp[curr_y]->ch[curr_x]; /* save location of cursor spot in window image */
- X curs_crflag = crflag; /* save crflag */
- X vt(VT_SETSPEC2); /* set flag and reverse video */
- X }
- X
- X
- X
- X
- X/* routine to handle line overflow */
- X/* returns nonzero if at end of screen, zero otherwise */
- X/* arg is current character position */
- X
- Xint w_overflow(wd)
- X {
- X wlp[curr_y]->end = wd-1; /* last character was end of this line */
- X if (wlp[curr_y]->n > curr_x)
- X {
- X wlp[curr_y]->n = curr_x;
- X if (curr_x < WN_width) vtm(VT_EEOL); /* if old line was wider, erase */
- X }
- X if (curr_y >= window_size-1) return(1);
- X wlp[curr_y]->cflag |= WF_BEG; /* mark this line as "continued" */
- X wlp[++curr_y]->cflag = WF_CONT; /* next line is a continuation line */
- X wlp[curr_y]->start = wd; /* char about to be printed is this line's first */
- X wlp[curr_y]->col = curr_x = 0; /* new line starts at left margin */
- X fputs("\033(0", stdout); /* alternate char set */
- X w_type('h', W_MARK); /* "NL" space */
- X w_type(' ', W_MARK);
- X fputs("\033(B", stdout);
- X return(0);
- X }
- X/* routine to type one character: arguments are char and a */
- X/* "mark" bit. If mark is set, the char is always retyped */
- X
- Xw_type(c, m)
- X char c;
- X int m;
- X {
- X register char *p;
- X
- X p = &wlp[curr_y]->ch[curr_x]; /* pointer to char image */
- X if ((c != *p) || (m) || (redraw_sw) || (curr_x >= wlp[curr_y]->n))
- X {
- X w_move(curr_y, curr_x);
- X putchar(c);
- X *p = (m) ? c | W_MARK : c;
- X ++term_x;
- X }
- X ++curr_x;
- X if (wlp[curr_y]->n < curr_x) wlp[curr_y]->n = curr_x; /* if we've lengthened the line, record that fact */
- X }
- X
- X
- X
- X
- X/* initialize display image */
- X
- Xw_init()
- X {
- X short i, j;
- X
- X for (i = 0; i < window_size; i++) /* for each row */
- X {
- X wlp[i] = &w_image[i]; /* set pointer to this line's data */
- X w_image[i].n = w_image[i].cflag = 0; /* no chars used, cr flag clear */
- X for (j = 0; j < W_MAX_H; w_image[i].ch[j++] = ' '); /* clear line */
- X }
- X }
- X
- X
- X
- X
- X/* put character followed by appropriate number of nulls for "other control function" */
- X/* if argument is 0, output filler chars only */
- X
- Xputchar_d(c)
- X char c;
- X {
- X int i;
- X
- X if (c) putchar(c); /* output character */
- X for (i = 0; i < win_dlyc[win_speed]; i++) putchar('\0'); /* output filler */
- X }
- X/* put out appropriate number of filler chars for display function that scrolls (LF, etc.) */
- X
- Xscroll_dly()
- X {
- X int i;
- X
- X for (i = 0; i < win_dlys[win_speed]; i++) putchar('\0'); /* output filler */
- X }
- X
- X
- X
- X/* move terminal cursor to stated y, x position */
- X/* uses incremental moves or absolute cursor position, whichever is shorter */
- X
- Xw_move(y, x)
- X short y, x;
- X {
- X register short i;
- X
- X /* if practical, use CR to get to left margin */
- X if ((curr_x == 0) && (term_x != 0)) putchar(CR), term_x = 0;
- X if ((y == term_y) && (term_x < WN_width)) /* if term x is beyond last char, use abs positioning */
- X {
- X if (x == term_x) return;
- X if (x > term_x)
- X {
- X if (x - term_x == 1) fputs("\033[C", stdout);
- X else printf("\033[%dC", x - term_x);
- X }
- X else
- X {
- X if ((i = term_x - x) < 4) for (; i > 0; i--) putchar('\b'); /* use BS */
- X else printf("\033[%dD", term_x - x); /* use incremental jump */
- X }
- X term_x = x;
- X }
- X else
- X {
- X if ((x == term_x) && (term_x < WN_width))
- X {
- X if (y > term_y)
- X {
- X if ((i = y - term_y) < 4) for (; i >0; i--) putchar(LF); /* use LF */
- X else printf("\033[%dB", i); /* use incremental jump */
- X }
- X else if ((i = term_y - y) == 1) fputs("\033[A", stdout); /* move 1 */
- X else printf("\033[%dA", i);
- X term_y = y;
- X }
- X else printf("\033[%d;%dH", (term_y = y) + 1, (term_x = x) + 1); /* absolute jump */
- X }
- X }
- X/* scroll screen: argument is count: + up, - down */
- X
- Xw_scroll(count)
- X int count;
- X {
- X register int i, ic;
- X struct w_line *p[W_MAX_V]; /* temp copy of pointer array */
- X
- X if (count > 0) /* scrolling up */
- X {
- X w_move(window_size-1, 0); /* cursor to bottom of window */
- X for (i = 0; i < count; i++)
- X {
- X putchar(LF), wlp[i]->n = 0; /* scroll terminal, blank out image line */
- X }
- X }
- X else /* scroll down */
- X {
- X w_move(0, 0); /* cursor to top */
- X for (i = 0; i > count; i--)
- X {
- X fputs("\033M", stdout), wlp[window_size-1+i]->n = 0;
- X }
- X }
- X for (i = 0; i < window_size; i++) p[i] = wlp[(window_size + i + count) % window_size]; /* rearrange */
- X for (i = 0; i < window_size; i++) wlp[i] = p[i];
- X }
- X
- X
- X
- X/* clear line to left of curr_x */
- X/* if some chars nonblank, does erase from start of line */
- X
- Xw_ebol()
- X {
- X short i, j;
- X
- X for (j = i = 0; i < curr_x; i++) if (wlp[curr_y]->ch[i] != ' ') wlp[curr_y]->ch[i] = ' ', j++;
- X if (j || redraw_sw) w_move(curr_y, curr_x-1), vt(VT_EBOL);
- X }
- X
- X
- X
- X/* routine to set a pointer to a given location (like set_pointer) */
- X/* returns nonzero if a text buffer exists, otherwise 0 */
- X
- Xint w_setptr(loc, pp)
- X register int loc; /* location */
- X register struct qp *pp; /* address of pointer */
- X {
- X register int i;
- X
- X if (buff.f)
- X {
- X for (i = loc / CELLSIZE, pp->p = buff.f; i > 0; i--) pp->p = pp->p->f;
- X pp->c = loc % CELLSIZE;
- X pp->dot = loc;
- X }
- X return( (int) buff.f);
- X }
- X/* routine to move N lines (back, forward, or 0) */
- X/* w_lines(n, &source, &dest) where n is the line count, source */
- X/* points to a qp at the current pointer, dest, if nonzero, */
- X/* it points to a qp where the result is to go. */
- X/* routine returns actual number of display lines */
- X
- Xstruct qp w_lines_p; /* to compute # of display lines in -N lines */
- X
- Xint w_lines(n, ps, pd)
- X int n; /* number of lines */
- X register struct qp *ps, *pd; /* source, destination qp's */
- X {
- X register struct buffcell *tp; /* local copy of the qp */
- X register int tc, tdot, tn;
- X int tcnt, tl; /* chars/line and display line count */
- X char tch;
- X
- X tdot = ps->dot;
- X tp = ps->p;
- X tc = ps->c;
- X
- X if (n > 0) /* argument is positive */
- X {
- X for (tcnt = tl = tn = 0; (tn < n) && (tdot < z); tdot++) /* forward over N line separators */
- X {
- X if (spec_chars[ tch = tp->ch[tc] ] & A_L) ++tl, ++tn; /* count separators */
- X else if (!(et_val & ET_TRUNC)) /* if text lines can overflow screen lines */
- X {
- X if (!(tch & 0140)) /* if character is a control char */
- X {
- X if (tch == CR) /* CR resets count */
- X {
- X if (tcnt > WN_width) ++tl;
- X tcnt = 0;
- X }
- X else if (tch == TAB) tcnt = (tcnt | tabmask) +1; /* tab to next tab stop */
- X else if (tch == ESC) ++tcnt; /* ESC takes one space */
- X else tcnt += 2; /* normal control chars take 2 spaces */
- X }
- X else ++tcnt; /* not a control char: takes one space */
- X if (tcnt > WN_width) ++tl, tcnt = 2; /* if overflow, one more line */
- X }
- X
- X if (++tc > CELLSIZE-1) tp = tp->f, tc = 0; /* next character position */
- X }
- X if (tl > tn) tn = tl; /* if counting display lines and there's more of them, return that */
- X }
- X else /* argument is zero or negative */
- X {
- X for (tn = 0; (tn >= n) && (tdot > 0); ) /* back up over (n+1) line feeds */
- X {
- X --tdot;
- X if (--tc < 0) tp = tp->b, tc = CELLSIZE -1;
- X if (spec_chars[tp->ch[tc]] & A_L) --tn;
- X }
- X if (tn < n) /* if stopped on a line sep, fwd over it */
- X {
- X ++tn;
- X ++tdot;
- X if (++tc > CELLSIZE-1) tp = tp->f, tc = 0;
- X }
- X
- X if (!(et_val & ET_TRUNC) && (n != 0)) /* if text line can overflow display line */
- X {
- X w_lines_p.dot = tdot, w_lines_p.p = tp, w_lines_p.c = tc; /* then count the number of display */
- X tn = -w_lines(-n, &w_lines_p, 0); /* lines in the N text lines we just backed up over */
- X }
- X }
- X
- X if (pd) pd->dot = tdot, pd->p = tp, pd->c = tc; /* if an "after" pointer given, update it */
- X return(tn);
- X }
- X
- END_OF_te_window.c
- if test 33018 -ne `wc -c <te_window.c`; then
- echo shar: \"te_window.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 4 \(of 4\).
- cp /dev/null ark4isdone
- DONE=true
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- echo shar: You still need to run archive ${I}.
- DONE=false
- fi
- done
- if test "$DONE" = "true" ; then
- echo You have unpacked all 4 archives.
- echo "See the *.doc files"
- rm -f ark[1-9]isdone
- fi
- ## End of shell archive.
- exit 0
-